//
//  SEChatMoreView.swift
//  SmartEyeForPatient
//
//  Created by QDSG on 2021/4/9.
//

import UIKit

private let kLeftRightPadding: CGFloat = 28.0
private let kTopBottomPadding: CGFloat = 18.0
private let kItemCountOfRow = 4

struct SEChatMoreItem {
    enum ItemType: Int {
        case photo, video, prescription, file
        
        var image: UIImage? {
            switch self {
            case .photo: return Asset.iconChatMorePhoto.image
            case .video: return Asset.iconChatMoreVideo.image
            case .prescription: return Asset.iconChatMorePrescription.image
            case .file: return Asset.iconChatMoreFile.image
            }
        }
    }
    
    var image: UIImage?
    
    private var _itemType = ItemType.photo
    var itemType: ItemType {
        get { _itemType }
        set {
            _itemType = newValue
            image = newValue.image
        }
    }
    
    init(itemType: ItemType) {
        self.itemType = itemType
    }
}

protocol SEChatMoreViewDelegate : NSObjectProtocol {
    func chatMoreView(_ moreView: SEChatMoreView, didClickedItemType itemType: SEChatMoreItem.ItemType)
}

class SEChatMoreView: UIView {
    
    weak var delegate: SEChatMoreViewDelegate?
    
    private let itemArray = [
        SEChatMoreItem(itemType: .photo),
        SEChatMoreItem(itemType: .video),
        SEChatMoreItem(itemType: .prescription),
        SEChatMoreItem(itemType: .file)
    ]
    
    @IBOutlet private weak var collectionViewHeightConstraint: NSLayoutConstraint!

    @IBOutlet private weak var collectionView: UICollectionView! {
        didSet {
            let flowLayout = SEChatMoreViewFlowLayout(columns: kItemCountOfRow, rows: 1)
            flowLayout.minimumLineSpacing = 20
            flowLayout.minimumInteritemSpacing = 0
            flowLayout.sectionInset = UIEdgeInsets(top: kTopBottomPadding,
                                                   left: kLeftRightPadding,
                                                   bottom: kTopBottomPadding,
                                                   right: kLeftRightPadding)
            
            let itemWidth = (UIScreen.screenWidth - kLeftRightPadding * 2 - flowLayout.minimumLineSpacing * CGFloat(kItemCountOfRow - 1)) / CGFloat(kItemCountOfRow)
            let itemHeight = (collectionView.height - kTopBottomPadding * 2) / 2
            flowLayout.itemSize = CGSize(width: itemWidth, height: itemHeight)
            
            collectionView.collectionViewLayout = flowLayout
            collectionView.scrollsToTop = false
            collectionView.isPagingEnabled = false
            collectionView.showsHorizontalScrollIndicator = false
            collectionView.delegate = self
            collectionView.dataSource = self
            
            collectionView.register(SEChatMoreViewCell.nibForCell(),
                                    forCellWithReuseIdentifier: SEChatMoreViewCell.reuseIdentifier())
        }
    }
}

extension SEChatMoreView: UICollectionViewDataSource, UICollectionViewDelegate {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return itemArray.count
    }
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: SEChatMoreViewCell.reuseIdentifier(),
                                                      for: indexPath) as! SEChatMoreViewCell
        cell.item = itemArray[indexPath.item]
        return cell
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        let item = itemArray[indexPath.item]
        delegate?.chatMoreView(self, didClickedItemType: item.itemType)
    }
}

class SEChatMoreViewFlowLayout: UICollectionViewFlowLayout {
    private var columns: Int = -1
    private var rows: Int = -1
    
    convenience init(columns: Int = 4, rows: Int = 1) {
        self.init()
        self.scrollDirection = .horizontal
        self.columns = columns
        self.rows = rows
    }
    
    override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes {
        guard let collectionView = collectionView else { return UICollectionViewLayoutAttributes() }
        
        let columns = self.columns >= 0 ? self.columns : Int(collectionView.width / itemSize.width)
        let rows = self.rows >= 0 ? self.rows : Int(collectionView.height / itemSize.height)
        
        let currentPage = indexPath.item / (columns * rows)
        let currentItem = indexPath.item - (currentPage * columns * rows)
        
        let currentRow = currentItem / columns
        let currentColumn = currentItem % columns
        
        let item = currentRow + currentColumn * rows + currentPage * columns * rows
        let currentIndexPath = IndexPath(item: item, section: indexPath.section)
        
        return super.layoutAttributesForItem(at: currentIndexPath)!
    }
    
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        let newX = min(0, rect.origin.x - rect.width / 2)
        let newWidth = rect.width * 2 + (rect.origin.x - newX)
        let newRect = CGRect(x: newX, y: rect.origin.y, width: newWidth, height: rect.height)
        
        guard let attributesArr = super.layoutAttributesForElements(in: newRect) else { return [] }
        var attributesArrCopy = [UICollectionViewLayoutAttributes]()
        
        for itemAttributes in attributesArr {
            let itemAttributesCopy = itemAttributes.copy() as! UICollectionViewLayoutAttributes
            attributesArrCopy.append(itemAttributesCopy)
        }
        
        return attributesArrCopy.map {
            let newAttributes = self.layoutAttributesForItem(at: $0.indexPath)
            $0.frame = newAttributes.frame
            $0.center = newAttributes.center
            $0.bounds = newAttributes.bounds
            $0.isHidden = newAttributes.isHidden
            $0.size = newAttributes.size
            return $0
        }
    }
    
    override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
        return true
    }
    
    override var collectionViewContentSize: CGSize {
        let size = super.collectionViewContentSize
        guard let collectionView = collectionView else { return size }
        let screen = Int(ceil(size.width / collectionView.width))
        return CGSize(width: CGFloat(screen) * collectionView.width, height: size.height)
    }
}
